home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ftp.whtech.com
/
ftp.whtech.com.tar
/
ftp.whtech.com
/
datasheets and manuals
/
Hardware
/
WHT
/
scsi
/
dsr_sources_2_2001
/
read
< prev
next >
Wrap
Text File
|
2006-10-19
|
24KB
|
975 lines
* I/O Opcode 2 - READ
*
* This routine will store the next record of the specified file
* in the user's buffer provided
* 1. The file is open
* 2. We have not reached end of file yet
*
* Once it determines that the file is open and not at end of file,
* it must determine if the contents of the buffer is valid. If not,
* it will read the next sector from the disk. If convient, it will
* read 2 sectors and use all 512 bytes of the buffer.
*
* Date: April 22, 1995
* Author: David Nieters
*
* Well, it's less than one week till Lima and I'm still writing
* new code. Let's home I get some of this working in time so it
* looks like it's 90% done like Don has been telling everybody.
*
* Modification History
*
* November 20, 1995 - Fixed directory file access to return the
* exact length for each filename instead of padded with
* spaces. Also, returns a null string when reached the
* end instead of 10 spaces. Will add subdirectory listings
* later.
*
READ0
ANDI R12,>FF00
AI R12,24
LDCR @B02,4 Select RAM bank 2
BLWP @IFO Check to make sure file is open
JEQ READ2
READ1 BL @DSRERR
DATA >0700 File error
READ2 CB @56(R5),@B02 See if file has been opened for reading
JEQ READ3
CB @56(R5),@ZERO or update access
JEQ READ3
CB @56(R5),@B05 Or directory access
JEQ READ3A
BL @DSRERR
DATA >0200 Bad open attribute?
READ3A B @READ60 Handle directory read
READ4 B @READ50 Handle the relative read
READ3 LDCR @ZERO,4 Check for sequential access
MOVB @PABBUF+1,R1 Get flags
ANDI R1,>0100
JNE READ4
LDCR @B02,4
* We know that the file is open and we are reading sequentially.
* Now check to see if we're at end of file.
*
MOV @4(R5),R1 Get FDR address
MOV @62(R5),R2 Get sector/record number
MOV @54(R5),R3 Get the pointer within the buffer
LDCR @2(R5),4 Select BANK with FDR
* If the file is empty, we must be reading
* past the end of file.
C @ZERO,@18(R1)
JEQ READ5
SWPB R2
C R2,@18(R1) See if we're in the last sector written
JNE READ7
* Here we check for fixed or variable length records. If fixed,
* the value in R2 was the last record written and we know we're
* at the end of the file. It the records are variable length, we
* check to see if we're pointing to an end of sector marker.
*
MOVB @12(R1),R0 Check for fixed or variable length
ANDI R0,>8000
JNE READ6
READ5
LDCR @B02,4 Close file if attempting to
CLR @4(R5) read past end of file
BL @DSRERR
DATA >0500 Attempt to read past end of file
READ6 LDCR @B02,4 Select RAM bank 2
LDCR @3(R5),4 Select bank with buffer
CB *R3,@B255 Are we at the end of the sector?
JEQ READ5
READ7 LDCR @B02,4 Select RAM bank 2
C @50(R5),@ZERO Have we read the 1st sector yet?
JNE READ20
* We have to read in the 1st sector of the file
*
LDCR @2(R5),4 Select bank with the FDR in it
MOV @40(R1),R7 Get 1st AU allocate in file
LDCR @B02,4 Select RAM bank 2
MOV R7,@50(R5) Save current AU
CLR @52(R5) We're reading 1st sector if this AU
CLR @58(R5) Set buffer size to 256 for now
MOV @6(R5),@54(R5) Set pointer to beginning of buffer
LDCR @B04,4 Select RAM bank 4
MOV R6,R3
SRL R3,8
SLA R3,1
MOV @SAUTBL(R3),R3 Get the Sectors/AU for this disk
MPY R3,R7
LI R1,SECBUF
SRL R8,1
JNC READ8
AI R1,>100
READ8 SRL R7,1
JNC READ9
AI R8,>8000
READ9 LDCR @ZERO,4
BLWP @BANKIT
DATA SCSIRD
JEQ READ10
BL @DSRERR
DATA >0600 Device error
* Now that we have read the block from the disk, see if we
* can use all 512 bytes, or only 256
*
READ10 LDCR @B02,4 Select RAM bank 2
CI R3,2 Make sure Sectors/AU > 1
JL READ11
CI R1,SECBUF Make sure we start at beginning
JNE READ11
SETO @58(R5) We're using all 512 bytes!
READ11
MOV @6(R5),R2 Get buffer address
MOVB @3(R5),R3 Get buffer bank number
READ12 LDCR @ZERO,4 Select RAM bank 0
MOV *R1+,R0
LDCR R3,4
MOV R0,*R2+
CI R1,SECBUF+512
JNE READ12
LDCR @B02,4 Select RAM bank 2
MOV @4(R5),R1 Get FDR address
LDCR @2(R5),4
MOVB @12(R1),R0 Set sector # to 1 if a variable file
ANDI R0,>8000
JEQ READ13
LDCR @B02,4
INC @62(R5)
READ13
B @READ40
*****************************************************
*
* Here we want to check to see if the buffer is
* valid. If it is not, then we must read the
* next sector into the buffer.
*
*****************************************************
READ20
LDCR @B02,4 Select RAM bank 2
MOV @4(R5),R1 Get pointer FDR
LDCR @2(R5),4
MOVB @12(R1),R2 Get file flags
LDCR @B02,4 Select RAM bank 2
ANDI R2,>8000 See if we have fixed length records
JNE READ2C
B @READ39
READ2C
MOV @54(R5),R1 Get pointer in buffer
LDCR @3(R5),4 Select bank with buffer in it
CB *R1,@B255 If it starts with >FF, it's end of sector
JEQ READ2B
B @READ40
READ2B
LDCR @B02,4 Select RAM bank 2
INC @62(R5) Increment sector number
* We're at the end of the sector. If we have a 512 byte buffer and
* we're still in the first 256 bytes, just go to second half of
* buffer. Otherwise, read the next sector from the disk.
*
READ21
LDCR @B02,4 Select RAM bank 2
C @58(R5),@ZERO See if we have a 512 byte buffer
JEQ RD21A
MOV @54(R5),R1 See if we're in 1st half of buffer
ANDI R1,>0100
JNE RD21A
MOV @54(R5),R1 OK, just go to next half
ANDI R1,>FF00
AI R1,>100
MOV R1,@54(R5) Save new pointer
INC @52(R5) Increment sector counter
LDCR @B04,4 Select RAM bank 4
MOV R6,R3
SRL R3,8
SLA R3,1
MOV @SAUTBL(R3),R3
LDCR @B02,4 Select RAM bank 2
C R3,@52(R5) See if we transcended an AU boundry
JNE RD21B
CLR @52(R5) Clear sector within AU
INC @50(R5) increment AU number
RD21B B @READ40
* Well, it looks like we're going to have to read the
* next sector from disk
*
RD21A
LDCR @B04,4 Select RAM bank 4
MOV R6,R3
SRL R3,8
SLA R3,1
MOV @SAUTBL(R3),R3
LDCR @B02,4 Select RAM bank 2
MOV @50(R5),R7 Get current AU
INC @52(R5) go to next sector within AU
C @52(R5),R3 See if we need to go to next AU
JNE READ25
* If this was the last AU in the cluster, we must go
* to the next cluster. Otherwise, just increment
* the current AU.
CLR @52(R5)
MOV @4(R5),R1 Get FDR address
LDCR @2(R5),4 Select bank with FDR
LI R10,54 There are 54 total clusters/FDR
AI R1,42
READ22 MOV *R1+,R2
JEQ READ23
C R2,R7
JEQ READ24
INCT R1
DEC R10
JNE READ22
READ23 INC R7
JMP READ25
READ24 MOV *R1,R7
READ25
LDCR @B02,4 Select RAM bank 2
MOV R7,@50(R5) Save current AU
MOV @6(R5),@54(R5) Reset pointer in buffer
CLR @58(R5) Set buffer size to 256 byte (for now)
MPY R3,R7
A @52(R5),R8 Add in sector within AU
JNC READ26
INC R7
READ26 LI R1,SECBUF
SRL R8,1
JNC READ27
AI R1,>100
READ27 SRL R7,1
JNC READ28
AI R8,>8000
READ28 LDCR @ZERO,4 Select RAM bank 0
BLWP @BANKIT Read the sector from disk
DATA SCSIRD
JEQ READ29
BL @DSRERR
DATA >0600 Device error
READ29
LDCR @B02,4
CI R3,2 See if we can use a 512 byte buffer
JL RD29A
CI R1,SECBUF
JNE RD29A
SETO @58(R5)
RD29A
MOV @6(R5),R2 Get buffer address
MOVB @3(R5),R4
READ30 LDCR @ZERO,4 Select RAM bank 0
MOV *R1+,R10
LDCR R4,4
MOV R10,*R2+
CI R1,SECBUF+512
JNE READ30
JMP READ40
R21HLP B @RD21A Help the JH instruction below
R22HLP B @READ21
* If we are handling fixed length records, we handle the
* buffer validity a little differently. Here goes
* If the pointer is exactly >200 greater than the base,
* we know we have to read the next sector. If it is
* exactly >100 greater than the base and the buffer size
* is 256 bytes, we have to read the next sector.
READ39 LDCR @B02,4 Select RAM bank 2
MOV @54(R5),R1 Get pointer within buffer
S @6(R5),R1 Subtract the base address
CI R1,>200
JEQ R21HLP
CI R1,>100
JNE RD39A
C @58(R5),@ZERO See if buffer size is 256
JEQ R21HLP If so, read next sector
INC @52(R5)
RD39A MOV @54(R5),R1 Get pointer within buffer
ANDI R1,>00FF
MOV @4(R5),R2 Get FDR address
LDCR @2(R5),4 Select bank with FDR
MOVB @17(R2),R4 Get record length
SRL R4,8
A R4,R1 See if we can add record length
CI R1,>0100 Without going over
JH R22HLP If not, read next sector
* We know the buffer is good. All we have to do now is
* transfer the record to the user's buffer.
READ40
* If we have a fixed length record, read that many bytes.
* If we have a variable length record, read the length
* byte first and read that many bytes.
*
LDCR @B02,4 Select RAM bank 2
MOV @54(R5),R2 Get buffer pointer
MOVB @3(R5),R3 Get buffer bank
MOV @4(R5),R1 Get Address of FDR
LDCR @2(R5),4 Select bank where FDR is
MOVB @12(R1),R0
ANDI R0,>8000 Mask out fixed/variable bit
JEQ READ44
* Well, we have a variable length record. Read the record
* size byte and store that many characters in the user's
* buffer.
*
LDCR R3,4
MOVB *R2+,R0
READ41
LDCR @ZERO,4 Store record size in user's PAB
MOV @PABADR,R1
ORI R1,>4000
AI R1,5
SWPB R1
MOVB R1,@VDPWA
SWPB R1
MOVB R1,@VDPWA
NOP
MOVB R0,@VDPWD
JEQ READ43 Skip copy if a null record
SRL R0,8
* Set the VDP write address to the user's buffer
*
MOV @PABBUF+2,R1
ORI R1,>4000
SWPB R1
MOVB R1,@VDPWA
SWPB R1
MOVB R1,@VDPWA
LDCR R3,4
READ42 MOVB *R2+,@VDPWD
DEC R0
JNE READ42
READ43 LDCR @B02,4
MOV R2,@54(R5)
LDCR @ZERO,4
B @DSRRT
READ44 MOVB @17(R1),R0 Get fixed record length
LDCR @B02,4 Select RAM bank 2
INC @62(R5) Increment last record # read.
JMP READ41
READ49 BL @DSRERR
DATA >0500 Attempt to read past end of file
**
*
* Here is where we handle relative access reads. The trick involves
* several divisions to compute where the record fits in the file.
*
**
READ50
BL @POSIT
LDCR @ZERO,4
MOV @PABADR,R1 Increment record # in caller's PAB
ORI R1,>4000
AI R1,6
SWPB R1
MOVB R1,@VDPWA
SWPB R1
MOVB R1,@VDPWA
MOV @PABBUF+6,R1
INC R1
MOVB R1,@VDPWD
SWPB R1
MOVB R1,@VDPWD
B @READ40 Transfer record to user and return
**
*
* Here is where we handle directory reads. Record 0 is the
* directory itself. Records 1-127 are files.
*
**
READ60
* Store the # of characters written in the caller's PAB
*
LDCR @ZERO,4 Select RAM bank 0
MOV @PABADR,R1
ORI R1,>4000
AI R1,5
SWPB R1
MOVB R1,@VDPWA
SWPB R1
MOVB R1,@VDPWA
LI R0,38*256 Store record length
MOVB R0,@VDPWD
* Set the VDP write address to the user's buffer
*
MOV @PABBUF+2,R1
ORI R1,>4000
SWPB R1
MOVB R1,@VDPWA
SWPB R1
MOVB R1,@VDPWA
* See which record we are reading
*
MOVB @PABBUF+1,R1
ANDI R1,>0100
JEQ READ61
MOV @PABADR,R1 Increment record # in caller's PAB
ORI R1,>4000
AI R1,6
SWPB R1
MOVB R1,@VDPWA
SWPB R1
MOVB R1,@VDPWA
MOV @PABBUF+6,R1
INC R1
MOVB R1,@VDPWD
SWPB R1
MOVB R1,@VDPWD
MOV @PABBUF+2,R1
ORI R1,>4000
SWPB R1
MOVB R1,@VDPWA
SWPB R1
MOVB R1,@VDPWA
MOV @PABBUF+6,R1
JMP READ62
READ61 LDCR @B02,4 Sequential read, get from cache
MOV @62(R5),R1
INC @62(R5)
READ62
CI R1,0 See if reading directory
JNE READ70
* Copy the directory name to the user's buffer
*
LDCR @B02,4
MOV @4(R5),R4
LDCR @2(R5),4
LI R0,10
AI R4,9
READ63 CB *R4,@SPACE
JNE RD63A
DEC R4
DEC R0
JNE READ63
RD63A SWPB R0
MOVB R0,@VDPWD Set name length
JEQ RD63C
SWPB R0
S R0,R4
INC R4
RD63B MOVB *R4+,@VDPWD
DEC R0
JNE RD63B
RD63C
* Now get the rest of the info
* R8 = Record type (Always zero)
* R9 = Total # of AU's on the disk
* R10 = # of free AU's on the disk
* Now get the number of free AU's on the disk. We read the
* entire bitmap from disk and count the number of zeros.
* There's got to be a better way to do this, and when I
* think of it, I'll change this code.
*
CLR R7
CLR R8
LI R4,SECBUF+>100 The bitmap is right after VIB
CLR R10 R10 Keeps track of # of free AU's
LDCR @ZERO,4
READ64 BLWP @BANKIT
DATA SCSIRD
JEQ READ65
AI R8,16 If error, read copy
BLWP @BANKIT
DATA SCSIRD
AI R8,-16
READ65
* If the value is 0, we can just add 16 to the number of
* free AU's. Otherwise, we have to count the bits in R1.
* If we just read the VIB, get the disk size here
CI R8,0
JNE RD65A
MOV @SECBUF+10,R5 Save in R5 for now
MOV @SECBUF+16,R2 Get sectors/AU
SRL R2,12
INC R2
RD65A
MOV *R4+,R1
JNE READ68
AI R10,16
READ66 CI R4,SECBUF+>200
JNE RD65A
READ67 LI R4,SECBUF
INC R8
CI R8,16
JNE READ64
* Now report the disk size and free space. We use
* the new 20 bit integer routine for this!
MOV R2,R9 Store Sectors/AU in another REG
CLR R1 File type = 0
CLR R2
BL @I20TOR
MOV R5,R1 Disk size in AU's
MPY R9,R1
BL @I20TOR
MOV R10,R1
MPY R9,R1
BL @I20TOR
LDCR @ZERO,4
B @DSRRT
READ68 CI R1,-1
JEQ READ66
LI R0,16
READ69 SLA R1,1
JOC RD69A
INC R10
RD69A DEC R0
JNE READ69
JMP READ66
* READ80 We're past all the filenames, return
* information on subdirectories now.
*
READ80 S R3,R1 Subtract # of files
MOVB @23(R2),R3 Get # of subdirectories
SRL R3,8
C R1,R3
JH READ81
B @READ91
READ81 CLR @VDPWD String length
LI R1,3 Return 3 RAXID 100 numbers
LI R2,>0808
READ82 MOV R2,@VDPWD
LI R3,8
READ83 CLR @VDPWD
DEC R3
JNE READ83
DEC R1
JNE READ82
LDCR @ZERO,4
B @DSRRT
**
*
* Here we are retrieving information about a file. If the
* record number is out of range, return all zeros.
*
**
READ70 LDCR @B02,4
MOV @4(R5),R2 Get DDR address
LDCR @2(R5),4
MOVB @22(R2),R3 Get # of files in directory
SRL R3,8
C R1,R3
JH READ80
* See if the FDIR has been loaded into the buffer. If it
* hasn't, read it in now
MOV @24(R2),R7 Get AU of FDIR just in case
LDCR @B02,4
C @58(R5),@ZERO
JNE READ75
SETO @58(R5) Set flag
MOV R6,R3 Read FDIR
SRL R3,8
SLA R3,1
LDCR @B04,4
MPY @SAUTBL(R3),R7
LI R2,SECBUF
SRL R8,1
JNC READ71
AI R2,>100
READ71 SRL R7,1
JNC READ72
AI R8,>8000
READ72 LDCR @ZERO,4
BLWP @BANKIT
DATA SCSIRD
JEQ READ73
BL @DSRERR
DATA >0600
READ73 LDCR @B02,4
MOV @6(R5),R3 Get buffer address
MOVB @3(R5),R4 Get buffer Bank
LI R0,256
READ74 LDCR @ZERO,4
MOV *R2+,R7
LDCR R4,4
MOV R7,*R3+
DECT R0
JNE READ74
READ75
DEC R1
SLA R1,1
LDCR @B02,4
MOV @6(R5),R4 Get address of buffer
LDCR @3(R5),4
A R1,R4
MOV *R4,R7 Get AU of FDR
LI R1,SECBUF
MOV R6,R3
SRL R3,8
SLA R3,1
LDCR @B04,4
MPY @SAUTBL(R3),R7
SRL R8,1
JNC READ76
AI R1,>100
READ76 SRL R7,1
JNC READ77
AI R8,>8000
READ77 LDCR @ZERO,4
BLWP @BANKIT
DATA SCSIRD
JEQ READ78
BL @DSRERR
DATA >0600
READ78 LI R0,10 Copy filename to user's buffer
MOV R1,R9
AI R1,9
RD78A CB *R1,@SPACE
JNE RD78B
DEC R1
DEC R0
JNE RD78A
RD78B SWPB R0
MOVB R0,@VDPWD File length shouldn't be zero
JEQ RD79Z but just in case...
SWPB R0
MOV R9,R1
READ79 MOVB *R1+,@VDPWD
DEC R0
JNE READ79
RD79Z MOV R9,R1
MOV @14(R1),R9 # of sectors allocated
MOVB @17(R1),R10 # of bytes/record
SRL R10,8
* Now see what type of file it is. We return the following
*
* 1: Display/Fixed
* 2: Display/Variable
* 3: Internal/Fixed
* 4: Internal/Variable
* 5: Program file
*
* If the file is protected, these numbers are inverted
LI R8,5
MOVB @12(R1),R0
ANDI R0,>0100 Check for program file
JNE RD79B
LI R8,1 Assume Display/Fixed
MOVB @12(R1),R0
ANDI R0,>8000 Check for variable records
JEQ RD79A
INC R8
RD79A MOVB @12(R1),R0
ANDI R0,>0200 Check for internal
JEQ RD79B
INCT R8
RD79B
* Now check to see if the file is protected
MOV @12(R1),R0
COC @PROBIT,R0
JNE RD79C
NEG R8
RD79C
* Now we just have to convert some 16 bit integers to radix 100
* format and store in the user's buffer and go home.
*
READ90
MOV R8,R2
BL @ITORAD
MOV R9,R2
BL @ITORAD
MOV R10,R2
BL @ITORAD
LDCR @ZERO,4
B @DSRRT
**
*
* READ91 - Here we return information on a subdirectory
*
**
READ91 DEC R1
SLA R1,1
LDCR @B02,4
MOV @4(R5),R4 Get address of DDR
LDCR @2(R5),4
A R1,R4
MOV @28(R4),R7 Get AU of subdirectory DDR
LI R1,SECBUF
MOV R6,R3
SRL R3,8
SLA R3,1
LDCR @B04,4
MPY @SAUTBL(R3),R7
SRL R8,1
JNC READ92
AI R1,>100
READ92 SRL R7,1
JNC READ93
AI R8,>8000
READ93 LDCR @ZERO,4
BLWP @BANKIT
DATA SCSIRD
JEQ READ94
BL @DSRERR
DATA >0600
READ94 LI R0,10 See how long the name is
MOV R1,R9
AI R1,9
READ95 CB *R1,@SPACE
JNE READ96
DEC R1
DEC R0
JNE READ95
READ96 SWPB R0
MOVB R0,@VDPWD Store directory name length
JEQ READ98
SWPB R0
MOV R9,R1
READ97 MOVB *R1+,@VDPWD
DEC R0
JNE READ97
READ98 MOV R9,R1
LI R8,6 File type = 6 for directory
LI R9,2 Size = 2 for now
CLR R10 Record size = 0?
JMP READ90
************************************************************
* *
* PROCEDURE ITORAD *
* *
* This procedure will take an unsigned integer stored in *
* R1 and convert it to RADIX 100 and store the result in *
* the file buffer. *
* *
************************************************************
ITORAD
MOVB @B08,@VDPWD Store field length (8 bytes)
CI R2,0
JEQ ITOR00
CI R2,100
JL ITOR1
CI R2,10000
JL ITOR3
* If it is greater than 65530, assume it's negative
CI R2,65530
JL ITOR50
* NEG R2
* ORI R2,>4000
* NEG R2
ANDI R2,>BFFF
MOVB R2,@VDPWD
SWPB R2
MOVB R2,@VDPWD
JMP ITOR1A
* Here we are converting a number in the range of 10000-65535
*
ITOR50
CLR R1
ITOR5A MOVB @HEX42,@VDPWD
LI R0,4
ITOR5B LI R3,10000
DIV R3,R1
SWPB R1
MOVB R1,@VDPWD
CLR R1
LI R3,100
DIV R3,R1
SWPB R1
MOVB R1,@VDPWD
SWPB R2
MOVB R2,@VDPWD
JMP ITOR2
* Here we are doing the number 0
*
ITOR00 LI R0,8
JMP ITOR2
* Here are are converting a number in the range of 0-99
*
ITOR1
MOVB @HEX40,@VDPWD
SWPB R2
MOVB R2,@VDPWD
ITOR1A LI R0,6
ITOR2 CLR @VDPWD
DEC R0
JNE ITOR2
RT
* Here we are converting a number in the range of 100-9999
*
ITOR3
MOVB @HEX41,@VDPWD
LI R0,5
ITOR3A
CLR R1
LI R3,100
DIV R3,R1
SWPB R1
MOVB R1,@VDPWD
SWPB R2
MOVB R2,@VDPWD
JMP ITOR2
************************************************************
* *
* I20TOR - Convert 20 bit integer to RADIX 100 *
* *
* This procedure will convert a 20 bit integer to RADIX *
* 100 format. The maximum size of a 20 bit integer is *
* 1,048,575. *
* *
* Input: R1, R2 = 20 bit integer (high 12 bits of R1 *
* must be zero). *
* *
* Uses: R0, R1, R2, R3 *
* *
************************************************************
I20TOR
MOVB @B08,@VDPWD Store field length (8 bytes)
CI R1,0
JNE I20TO2
CI R2,0
JEQ ITOR00 Number is zero
CI R2,100
JL ITOR1 Number is 1-99
CI R2,10000
JL ITOR3 Number is 100-9999
JMP ITOR5A Number is 10000-65535
I20TO2
* OK. The number is greater than 65535. See if it's
* less than 1,000,000
*
CI R1,15
JL ITOR5A Number is < 983,040
CI R2,16960
JL ITOR5A
**
*
* Here we handle numbers 1,000,000-1,048,575
*
**
I20TO5 MOVB @HEX43,@VDPWD
LI R0,3
MOVB @B01,@VDPWD
CLR R1
AI R2,-16960
JMP ITOR5B
HEX40 BYTE >40
HEX41 BYTE >41
HEX42 BYTE >42
HEX43 BYTE >43